package com.rrjjg.app.core.config;

import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.alibaba.fastjson.support.config.FastJsonConfig;
import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;
import com.rrjjg.app.core.Constants;
import com.rrjjg.app.core.aop.LogAop;
import com.rrjjg.app.core.properties.OkHttpPro;
import lombok.extern.slf4j.Slf4j;
import okhttp3.*;
import okio.Buffer;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.MDC;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.HttpMessageConverter;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.concurrent.TimeUnit;

/**
 * ----------------------------------------------------------------------------- <br>
 * 功能 :  <br>
 * ----------------------------------------------------------------------------- <br>
 * 作者 : Vayne <br>
 * 时间 : 2023/4/8 <br>
 */
@Slf4j
@Configuration
public class CoreConfig {

    /* 装配okhttp */
    @ConditionalOnBean(OkHttpPro.class)
    @Bean
    public okhttp3.OkHttpClient okHttpClient(OkHttpPro okHttpPro) throws Exception {
        okhttp3.OkHttpClient.Builder builder = new okhttp3.OkHttpClient.Builder();
        Dispatcher dispatcher = new Dispatcher();
        dispatcher.setMaxRequests(okHttpPro.getMaxRequests());
        dispatcher.setMaxRequestsPerHost(okHttpPro.getMaxRequestsPerHost());
        X509TrustManager trustManager = new X509TrustManager() {
            @Override
            public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
            }
            @Override
            public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
            }
            @Override
            public X509Certificate[] getAcceptedIssuers() {
                return new X509Certificate[0];
            }
        };
        SSLContext sslContext = SSLContext.getInstance("TLS");
        sslContext.init(null, new TrustManager[]{trustManager}, null);
        builder.connectTimeout(okHttpPro.getConnectTimeout(), TimeUnit.MILLISECONDS)
                .readTimeout(okHttpPro.getReadTimeout(), TimeUnit.MILLISECONDS)
                .writeTimeout(okHttpPro.getWriteTimeout(), TimeUnit.MILLISECONDS)
                .dispatcher(dispatcher)
                .connectionPool(new ConnectionPool(okHttpPro.getMaxIdleConnections(), okHttpPro.getKeepAliveDuration(), TimeUnit.MILLISECONDS))
                .sslSocketFactory(sslContext.getSocketFactory(), trustManager)
                .addInterceptor(new Interceptor() {
                    @Override
                    public Response intercept(Chain chain) throws IOException {
                        Response response = null;
                        try {
                            Request request = chain.request();
                            String trackId = MDC.get(Constants.LOG_ID);
                            if (StringUtils.isNotEmpty(trackId)) {
                                request = request.newBuilder().addHeader(Constants.LOG_ID, trackId).build();
                            }
                            JSONObject logBody = new JSONObject();
                            RequestBody body = request.body();
                            if (body != null) {
                                Buffer buffer = new Buffer();
                                body.writeTo(buffer);
                                String param = buffer.readString(StandardCharsets.UTF_8);
                                logBody.put(Constants.LOG_PAR, param);
                            }
                            long s = System.currentTimeMillis();
                            String url = request.url().toString();
                            logBody.put(Constants.LOG_URL, url);
                            response = chain.proceed(request);
                            long e = System.currentTimeMillis();
                            ResponseBody responseBody = response.peekBody(1024 * 1024);
                            logBody.put(Constants.LOG_RES, responseBody.string());
                            logBody.put(Constants.LOG_STA, response.code());
                            logBody.put(Constants.LOG_TI, e - s);
                            log.info("feign call: {} ", logBody);
                        } catch (Exception e) {
                            log.error("feign call", e);
                        }
                        return response;
                    }
                });
        return builder.build();
    }


    @Bean
    public LogAop logAop(){
        return new LogAop();
    }

    /*使用fastjson*/
    @Bean
    public HttpMessageConverters fastJsonHttpMessageConverters() {
        FastJsonHttpMessageConverter fastConverter = new FastJsonHttpMessageConverter();
        FastJsonConfig fastJsonConfig = new FastJsonConfig();
        fastJsonConfig.setSerializerFeatures(SerializerFeature.PrettyFormat);
        fastConverter.setFastJsonConfig(fastJsonConfig);
        HttpMessageConverter<?> converter = fastConverter;
        return new HttpMessageConverters(converter);
    }
}
